<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务，帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2021 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件，不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types = 1);

namespace app\api\model\store;

use app\api\model\ding\ShopFoodsRel as ShopFoodsRelModel;
use app\api\model\ding\ShopImages as ShopImagesModel;
use app\api\model\ding\ShopTypeRel as ShopTypeRelModel;
use app\api\model\store\shop\Diy as ShopDiyModel;
use app\api\model\wxapp\Setting as WxappSettingModel;
use app\api\service\User as UserService;
use app\common\library\wechat\Link;
use app\common\model\store\Shop as ShopModel;
use think\facade\Db;

/**
 * 商家门店模型
 * Class Shop
 * @package app\store\model\store
 */
class Shop extends ShopModel
{
    /**
     * 隐藏字段
     * @var array
     */
    protected $hidden = [
        'is_delete',
        'store_id',
        'create_time',
        'update_time',
    ];
    public function bind($data)
    {
        $userId = UserService::getCurrentLoginUserId();

        $clerkInfo = Db::name('store_shop_clerk')->where('is_delete', 0)->where('shop_id', $this['shop_id'])->where('user_id', $userId)->find();

        if ($clerkInfo) {

            $data['shop_id'] = $this['shop_id'];

            Db::name('store_shop_clerk')->where('clerk_id', $clerkInfo['clerk_id'])->update($data);
            $id = $clerkInfo['clerk_id'];
        } else {
            //查询是否有oauth_id
            $oauth_id         = Db::name('store_shop_clerk')->where('mobile', $data['mobile'])->value('oauth_id');
            $data['shop_id']  = $this['shop_id'];
            $data['user_id']  = $userId;
            $data['oauth_id'] = $oauth_id ? $oauth_id : '';

            $data['create_time'] = time();
            $data['store_id']    = self::$storeId;
            $id                  = Db::name('store_shop_clerk')->insertGetId($data);

        }
        //员工链接
        // 获取当前小程序信息
        $config = self::getMpWxConfig();
        // 微信登录 (获取session_key)
        $WxUser                = new Link($config['app_id'], $config['app_secret']);
        $param['page_url']     = 'pagesNew/shop/share?' . 'clerkId=' . $id . '&shopId=' . $this['shop_id'] . '&source=3';
        $param['page_title']   = '找我预订';
        $param['is_permanent'] = true;
        //$param['query'] = 'clerkId=' . $id . '&shopId=' . $this['shop_id'];
        $result = $WxUser->getLink($param);
        $url    = $result['link'];

        Db::name('store_shop_clerk')->where('clerk_id', $id)->update(['url' => $url]);
        return true;
    }
    /**
     * 获取微信小程序配置项
     * @return array
     * @throws \cores\exception\BaseException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */

    private static function getMpWxConfig(): array
    {
        $wxConfig = WxappSettingModel::getWxappConfig();
        if (empty($wxConfig['app_id']) || empty($wxConfig['app_secret'])) {
            throwError('请到后台小程序设置填写AppID和AppSecret参数');
        }
        return $wxConfig;
    }
    public function edit(array $data)
    {

        // 菜系
        ShopFoodsRelModel::updated((int) $this['shop_id'], $data['foods']);

        // 餐厅类型
        ShopTypeRelModel::updated((int) $this['shop_id'], $data['typeList']);
        // 门店照片
        ShopImagesModel::updated((int) $this['shop_id'], $data['uploaded']);
        $data['shop_hours'] = $data['start_time'] . '-' . $data['end_time'];

        if (! empty($data['tags'])) {
            $data['tags'] = implode(';', $data['tags']);
        }

        // 更新
        return $this->save($data) !== false;
    }
    public function diySave(array $data)
    {
        Db::name('store_shop_diy')->where('shop_id', $this['shop_id'])->delete();

        if (! empty($data['contentList'])) {
            ShopDiyModel::increased((int) $this['shop_id'], $data['contentList']);
            $this->save(['diy_title' => $data['title'], 'is_setting' => 1]);
        } else {
            $this->save(['diy_title' => $data['title'], 'is_setting' => 0]);
        }

        // 更新
        return true;
    }
    public function setting(array $data)
    {

        // 更新
        return $this->save($data) !== false;
    }

    public function getListZhuanqu(array $param = [])
    {
        // 查询构造器
        $query = $this->getNewQuery();
        // 设置列表查询条件
        $filter = $this->getFilter($param);

        // 获取门店列表数据
        $list = $query->with(['logoImage', 'foods.food'])
            ->where($filter)
            ->where('is_delete', '=', 0)
            ->where('status', '=', 1)
            ->where('is_hot', '=', 1)
            ->order(['sort' => 'asc'])
            ->select();

        foreach ($list as $key => $value) {
            if ($value['foods']) {
                $caixi               = array_column($value['foods']->toArray(), 'name');
                $list[$key]['caixi'] = implode(' | ', $caixi);
            } else {
                $list[$key]['caixi'] = '';
            }

        }

        return $list;
    }
    /**
     * 获取门店列表
     * @param array $param 查询参数
     * @param int|null $limit 查询条数
     * @return array|\think\Collection
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getList(array $param = [], int $limit = null)
    {

        // 查询构造器
        $query = $this->getNewQuery();
        // 设置列表查询条件
        $filter = $this->getFilter($param);
        // 获取数量
        $limit > 0 && $query->limit($limit);

        $lng   = $param['longitude'];
        $lat   = $param['latitude'];
        $EARTH = 6378.137;        //地球半径
        $PI    = 3.1415926535898; //PI值
        if ($lng) {

        } else {
            return [];
        }

        $sql    = "ROUND(6378.138 * 2 * ASIN(SQRT(POW(SIN(($lat * PI() / 180 - latitude * PI() / 180) / 2), 2) + COS($lat * PI() / 180) * COS(latitude * PI() / 180) * POW(SIN(($lng * PI() / 180 - longitude * PI() / 180) / 2), 2))) * 1000) AS distance";
        $having = '';
        if ($param['juli_index'] > -1) {
            switch ($param['juli_index']) {
                case 0:
                    $having = 'distance <=500';
                    break;
                case 1:
                    $having = 'distance <=1000';
                    break;
                case 2:
                    $having = 'distance <=3000';
                    break;
                case 3:
                    $having = 'distance <=5000';
                    break;
                case 4:
                    $having = 'distance >5000';
                    break;
                default:
                    $having = '';
                    break;
            }
        }

        // 获取门店列表数据
        $sql = Db::name('store_shop')
            ->where($filter)
            ->where('is_delete', '=', 0)
            ->where('status', '=', 1)
            ->field(['*', Db::raw($sql)])
            ->order(['distance' => 'asc', 'sort' => 'asc'])
            ->having($having)
            ->buildSql();

        $list = Db::table($sql)
            ->alias('a')->paginate(10)
            ->each(function ($item, $key) {
                $shop             = $this->with(['logoImage', 'foods.food'])->where('shop_id', $item['shop_id'])->find();
                $item['tags']     = $shop['tags'];
                $item['foods']    = $shop['foods'];
                $item['logo_url'] = $shop['logoImage']['preview_url'];

                if ($item['foods']) {
                    $caixi         = array_column($item['foods']->toArray(), 'name');
                    $item['caixi'] = implode(' | ', $caixi);
                } else {
                    $item['caixi'] = '';
                }

                $distance = $item['distance'];
                if ($distance >= 1000) {
                    $distance         = bcdiv((string) $distance, (string) 1000, 2);
                    $item['distance'] = $distance . 'km';
                } else {
                    $item['distance'] = round($distance) . 'm';
                }
                return $item;

            });

        return $list;
    }

    /**
     * 设置列表查询条件
     * @param array $param
     * @return array
     */
    private function getFilter(array $param = []): array
    {
        // 默认查询参数
        $params = $this->setQueryDefaultValue($param, [
            'isCheck'      => -1, // 是否支持自提核销(0否 1支持)
            'longitude'    => '', // 用户位置: 经度
            'latitude'     => '', // 用户位置: 纬度
            'search'       => '',
            'foodsList'    => '',
            'city'         => '',
            'area_index'   => -1,
            'juli_index'   => -1,
            'money_min'    => 0,
            'money_max'    => 0,
            'shop_type_id' => -1,
            'district_id'  => -1, //行政区

        ]);

        // 检索查询条件
        $filter = [];
        // 是否支持自提核销
        $params['isCheck'] > -1 && $filter[] = ['is_check', '=', (int) $params['isCheck']];

        $params['district_id'] > 0 && $filter[] = ['region_id', '=', (int) $params['district_id']];

        if ($params['money_min'] > 0) {
            $filter[] = ['money', '>=', (int) $params['money_min']];
            $filter[] = ['money', '<=', (int) $params['money_max']];
        }
        if ($params['shop_type_id'] > 0) {
            $ids = Db::name('ding_shop_type_rel')->where('type_id', $params['shop_type_id'])
                ->field('shop_id')->group('shop_id')->select()->toArray();
            if ($ids) {
                $ids      = array_column($ids, 'shop_id');
                $filter[] = ['shop_id', 'in', $ids];
            } else {
                $filter[] = ['shop_id', '=', -1];
            }
        }
        ! empty($params['search']) && $filter[] = ['shop_name', 'like', '%' . $params['search'] . '%'];
        $foodsList                             = json_decode($params['foodsList'], true);

        if ($foodsList) {
            $ids = Db::name('ding_shop_foods_rel')->where('food_id', 'in', $foodsList)
                ->field('shop_id')->group('shop_id')->select()->toArray();
            if ($ids) {
                $ids      = array_column($ids, 'shop_id');
                $filter[] = ['shop_id', 'in', $ids];
            } else {
                $filter[] = ['shop_id', '=', -1];
            }

        }
        ! empty($params['city']) && $filter[] = ['city', '=', $params['city']];

        return $filter;
    }
    /*
		     *根据关键字搜索周边地区
	*/
    public function getMapList($search = '', $city, $longitude, $latitude)
    {

        $key = 'LJ2BZ-LXDCG-MBKQV-QGB2N-4YXXF-GIFL4';
        $lat = '22.800237,108.337555,15000';
        //$url = 'https://apis.map.qq.com/ws/place/v1/search?boundary=nearby('.$lat.')&keyword=南宁&page_size=10&page_index=10&key=' . $key;
        $url    = 'https://apis.map.qq.com/ws/place/v1/suggestion?address_format=short&region=' . $city . '&region_fix=1&keyword=' . $search . '&page_size=10&page_index=1&key=' . $key;
        $result = $this->curlGet($url);
        $result = json_decode($result, true);
        $list   = $result['data'];

        foreach ($list as &$item) {

            // 计算距离
            $distance = self::getDistance((float) $longitude, (float) $latitude, (float) $item['location']['lng'], (float) $item['location']['lat']);

            if ($distance >= 1000) {
                $distance         = bcdiv((string) $distance, (string) 1000, 2);
                $item['distance'] = $distance . 'km';
            } else {
                $item['distance'] = $distance . 'm';
            }

        }

        return $list;
    }

    /**
     * curl请求指定url
     * @param $url
     * @param array $data
     * @return bool|string
     */
    private function curlGet($url, array $data = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $response = curl_exec($ch);
        curl_close($ch);
        return $response;
    }
    /**
     * 根据距离排序
     * @param $data
     * @param string $longitude 经度
     * @param string $latitude 纬度
     * @return array
     */
    private function sortByDistance($data, string $longitude, string $latitude)
    {
        // 根据距离排序
        $list    = $data->isEmpty() ? [] : $data->toArray();
        $sortArr = [];
        foreach ($list as &$shop) {
            if ($shop['foods']) {
                $caixi         = array_column($shop['foods'], 'name');
                $shop['caixi'] = implode(' | ', $caixi);
            } else {
                $shop['caixi'] = '';
            }

            // 计算距离
            $distance = self::getDistance((float) $longitude, (float) $latitude, (float) $shop['longitude'], (float) $shop['latitude']);
            // 排序列
            $sortArr[]        = $distance;
            $shop['distance'] = $distance;
            if ($distance >= 1000) {
                $distance              = bcdiv((string) $distance, (string) 1000, 2);
                $shop['distance_unit'] = $distance . 'km';
            } else {
                $shop['distance_unit'] = $distance . 'm';
            }

        }
        // 根据距离排序
        array_multisort($sortArr, SORT_ASC, $list);
        return $list;
    }

    /**
     * 获取两个坐标点的距离
     * @param float $ulon
     * @param float $ulat
     * @param float $slon
     * @param float $slat
     * @return float
     */
    private static function getDistance(float $ulon, float $ulat, float $slon, float $slat)
    {
        // 地球半径
        $R = 6378137;
        // 将角度转为狐度
        $radLat1 = deg2rad($ulat);
        $radLat2 = deg2rad($slat);
        $radLng1 = deg2rad($ulon);
        $radLng2 = deg2rad($slon);
        // 结果
        $s = acos(cos($radLat1) * cos($radLat2) * cos($radLng1 - $radLng2) + sin($radLat1) * sin($radLat2)) * $R;
        // 精度
        $s = round($s * 10000) / 10000;
        return round($s);
    }

    /**
     * 根据门店id集获取门店列表
     * @param array $shopIds
     * @return \think\Collection|false
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getListByIds(array $shopIds)
    {
        if (empty($shopIds)) {
            return false;
        }
        // 筛选条件
        $filter = [['shop_id', 'in', $shopIds]];
        // 获取商品列表数据
        return $this->with(['logoImage'])
            ->orderRaw('field(shop_id, ' . implode(',', $shopIds) . ')')
            ->where('is_delete', '=', '0')
            ->where('status', '=', '1')
            ->where($filter)
            ->select();
    }

}
